#include <stdio.h>          // 标准输入输出
#include <stdlib.h>         // 标准函数库
#include <string.h>         // 字符串处理(操作字符数组)

#include "ohos_init.h"      // 用于初始化服务(services)和功能(features)
#include "cmsis_os2.h"      // CMSIS-RTOS API V2

#include "wifi_connecter.h" // easy wifi (station模式)
#include "mqtt_task.h"      // MQTT接口

#include "iot_gpio.h"
#include "hi_gpio.h"
// 海思SDK接口：IoT硬件设备操作接口-IO
// 海思SDK接口，以hi_io_set_func(...)
#include "hi_io.h"

// 定义GPIO引脚
#define SCK_GPIO 0
#define DOUT_GPIO 1

#define GapValue 205
// float Weight=0;
uint32_t Weight_Maopi = 0;
uint32_t HX711_Buffer = 0;
int32_t Weight_Shiwu = 0;

// 定义一个宏，用于标识SSID。请根据实际情况修改
#define PARAM_HOTSPOT_SSID "Redmi"

// 定义一个宏，用于标识密码。请根据实际情况修改
#define PARAM_HOTSPOT_PSK "264557abc"

// 定义一个宏，用于标识加密方式
#define PARAM_HOTSPOT_TYPE WIFI_SEC_TYPE_PSK

// 定义一个宏，用于标识MQTT服务器IP地址。请根据实际情况修改
#define PARAM_SERVER_ADDR "182.92.158.237"

// 定义一个宏，用于标识MQTT服务器端口
#define PARAM_SERVER_PORT "1883"


uint32_t Hx711_Read(void)
{
    unsigned long count;
    unsigned char i;
    IotGpioValue value = IOT_GPIO_VALUE0;
    IoTGpioGetInputVal(DOUT_GPIO, &value);
    osDelay(0.001);
    IoTGpioSetOutputVal(SCK_GPIO, IOT_GPIO_VALUE0); // 输出高电平
    osDelay(0.001);
    count = 0;
    // 获取GPIO5引脚的输入电平（1高电平，0低电平）
    // 调用IoTGpioGetInputVal接口
    do
    {
        IoTGpioGetInputVal(DOUT_GPIO, &value);
    } while (value);
    for (i = 0; i < 24; i++)
    {
        // IoTGpioSetOutputVal(SCK_GPIO, i%2?IOT_GPIO_VALUE1:IOT_GPIO_VALUE0); // 状态验证
        IoTGpioSetOutputVal(SCK_GPIO, IOT_GPIO_VALUE1); // 输出高电平
        osDelay(0.001);
        count = count << 1;                             // 左移一位
        IoTGpioSetOutputVal(SCK_GPIO, IOT_GPIO_VALUE0); // 输出低电平
        osDelay(0.001);
        IoTGpioGetInputVal(DOUT_GPIO, &value);
        // printf("%d", value);
        if (value)
        {
            count++;
        }
    }
    IoTGpioSetOutputVal(SCK_GPIO, IOT_GPIO_VALUE1);
    count = count ^ 0x800000;
    osDelay(0.001);
    IoTGpioSetOutputVal(SCK_GPIO, IOT_GPIO_VALUE0);
    osDelay(0.001);
    return count;
}

int32_t Get_Weight()
{
    HX711_Buffer = Hx711_Read();
    if(HX711_Buffer > Weight_Maopi)
    {
    Weight_Shiwu = HX711_Buffer;
    Weight_Shiwu = Weight_Shiwu - Weight_Maopi;               // 获取实物的AD采样数值。
    Weight_Shiwu = (int32_t)((float)Weight_Shiwu / GapValue); // 计算实物的实际重量
                                                                  // 因为不同的传感器特性曲线不一样，因此，每一个传感器需要矫正这里的GapValue这个除数。
                                                                  // 当发现测试出来的重量偏大时，增加该数值。
																	//如果测试出来的重量偏小时，减小改数值。
    }
    return Weight_Shiwu;
}



// 主线程函数
static void mqttDemoTask(void *arg)
{
    (void)arg;


    // 初始化GPIO模块
    IoTGpioInit(SCK_GPIO);
    IoTGpioInit(DOUT_GPIO);

    // 设置GPIO0为GPIO功能
    hi_io_set_func(SCK_GPIO, HI_IO_FUNC_GPIO_0_GPIO);

    // 设置GPIO0为输出模式
    IoTGpioSetDir(SCK_GPIO, IOT_GPIO_DIR_OUT);

    // 设置GPIO1为GPIO功能
    hi_io_set_func(DOUT_GPIO, HI_IO_FUNC_GPIO_1_GPIO);

    // 设置GPIO1为输入模式
    IoTGpioSetDir(DOUT_GPIO, IOT_GPIO_DIR_IN);


    Weight_Maopi = Hx711_Read();
    osDelay(200);
    // while (1)
    // {

    //     float weight=Get_Weight();
    //         printf("净重量 = %d g\r\n", Weight_Shiwu); // 打印
    //     osDelay(100);
    // }

    // 连接AP
    // 定义热点配置
    WifiDeviceConfig config = {0};
    // 设置热点配置中的SSID
    strcpy(config.ssid, PARAM_HOTSPOT_SSID);
    // 设置热点配置中的密码
    strcpy(config.preSharedKey, PARAM_HOTSPOT_PSK);
    // 设置热点配置中的加密方式
    config.securityType = PARAM_HOTSPOT_TYPE;
    // 等待100ms
    osDelay(10);
    // 连接到热点
    int netId = ConnectToHotspot(&config);
    // 检查是否成功连接到热点
    if (netId < 0)
    {
        printf("Connect to AP failed!\r\n");
        return;
    }

    // 初始化并启动MQTT任务，连接MQTT服务器
    MqttTaskInit();                                                     // 初始化并启动MQTT任务
    const char *host = PARAM_SERVER_ADDR;                               // MQTT服务器IP地址
    unsigned short port = atoi(PARAM_SERVER_PORT);                      // MQTT服务器端口
    const char *clientId = "project";                               // MQTT客户端ID
    const char *username = "admin";                                        // MQTT服务器用户名
    const char *password = "123";                                        // MQTT服务器密码
    if (MqttTaskConnect(host, port, clientId, username, password) != 0) // 连接MQTT服务器
    {
        // 连接失败，输出错误信息并退出
        printf("Connect to MQTT server failed!\r\n");
        return;
    }

    // 订阅主题"test/b"
    char *stopic = "Open/devices/hx711/project";            // 主题
    int rc = MqttTaskSubscribe(stopic); // 订阅主题
    if (rc != 0)
    {
        // 订阅失败，输出错误信息并退出
        printf("MQTT Subscribe failed!\r\n");
        return;
    }
    // 输出订阅成功信息
    printf("MQTT Subscribe OK\r\n");

    // 向主题"test/a"发布一条消息
    char *ptopic = "Open/devices/hx711/project1";                            // 主题
    char *payload = "{\"device_id\":\"hx711\", \"status\":\"online\"}"; // 消息内容
    rc = MqttTaskPublish(ptopic, payload);              // 发布消息
    if (rc != 0)
        printf("MQTT Publish failed!\r\n");             // 发布失败，输出错误信息
    else
        printf("MQTT Publish OK\r\n");                  // 发布成功，输出成功信息
    
    while (1)
    {
        char payload[64] = {0};                                         // 消息内容
        snprintf(payload, sizeof(payload),
                 "{\"device_id\":\"hx711\", \"weight\":\"%d\"}",
                 Get_Weight());                                      // 获取数据
        int rc = MqttTaskPublish(ptopic, payload);                      // 发布消息
        if (rc != 0)                                                    // 检查是否成功发布消息
            printf("MQTT Publish failed!\r\n");
        else
            printf("MQTT Publish OK\r\n");
            printf("净重量 = %d g\r\n", Weight_Shiwu); // 打印
        osDelay(100);                                                   // 发布消息间隔1秒。实际上报无需这么频繁
    }

    // while (1)
    // {
    //     char payload[64] = {0};                             // 消息内容
    //     // float Weight_Shiwu = 0.0f;                              //  重量
    //     // if (Get_Weight(&Weight_Shiwu) == 0) //成功获取数字温湿度传感器数据
    //     // {
    //         snprintf(payload, sizeof(payload),
    //                  "{\"device_id\":\"hx711\", \"weight\":%d}",
    //                  Get_Weight());                // 消息内容采用JSON格式
    //         rc = MqttTaskPublish(ptopic, payload);          // 发布消息
    //         if (rc != 0)                                    // 检查是否成功发布消息
    //             printf("MQTT Publish failed!\r\n");
    //         else
    //             printf("MQTT Publish OK\r\n");
    //     // }
    //     osDelay(100);                                       // 发布消息间隔1秒。实际上报无需这么频繁
    // }



    // char *ptopic = "$oc/devices/6612816171d845632a043edd_hi3861/sys/properties/report";

    // // 工作循环
    // while (1)
    // {
    //     char payload[512] = {0};                            // 消息内容
    //     float temperature = 0.0f;                           // 温度
    //     float humidity = 0.0f;                              // 湿度
    //     if (GetTempHumiLevel(&temperature, &humidity) == 0) //成功获取数字温湿度传感器数据
    //     {
    //         // 消息内容采用JSON格式
    //         //
    //         // 主题：设备消息上报
    //         // 格式：https://support.huaweicloud.com/api-iothub/iot_06_v5_3016.html
    //         // 例如：{"content":{"temperature":22.30,"humidity":50.10}}
    //         //
    //         // 主题：设备上报属性数据
    //         // 格式：https://support.huaweicloud.com/api-iothub/iot_06_v5_3010.html
    //         // 例如：
    //         // {
    //         //     "services": [{
    //         //             "service_id": "smokeDetector",
    //         //             "properties": {
    //         //                 "temperature": 22.30
    //         //             }
    //         //         },
    //         //         {
    //         //             "service_id": "smokeDetector",
    //         //             "properties": {
    //         //                 "humidity": 50.10
    //         //             }
    //         //         }
    //         //     ]
    //         // }
    //         //
    //         // 可以简化一下：
    //         // {
    //         //     "services": [{
    //         //         "service_id": "smokeDetector",
    //         //         "properties": {"temperature": 22.30, "humidity": 50.10}
    //         //     }]
    //         // }

    //         // 主题：设备消息上报
    //         // snprintf(payload, sizeof(payload),
    //         //          "{\"content\":{\"temperature\":%.2f,\"humidity\":%.2f}}", temperature, humidity);

    //         // 主题：设备上报属性数据
    //         // https://www.bejson.com/ -> 格式化校验 -> 压缩 -> 转义
    //         //
    //         // {\"services\":[{\"service_id\":\"smokeDetector\",\"properties\":{\"temperature\":22.30}},{\"service_id\":\"smokeDetector\",\"properties\":{\"humidity\":50.10}}]}
    //         // snprintf(payload, sizeof(payload),
    //         //  "{\"services\":[{\"service_id\":\"smokeDetector\",\"properties\":{\"temperature\":%.2f}},{\"service_id\":\"smokeDetector\",\"properties\":{\"humidity\":%.2f}}]}", temperature, humidity);
    //         //
    //         // {\"services\":[{\"service_id\":\"smokeDetector\",\"properties\":{\"temperature\":22.30,\"humidity\":50.10}}]}
    //         snprintf(payload, sizeof(payload),
    //                  "{\"services\":[{\"service_id\":\"smokeDetector\",\"properties\":{\"temperature\":%.2f,\"humidity\":%.2f}}]}", 
    //                  temperature, humidity);    // 消息内容采用JSON格式

    //         int rc = MqttTaskPublish(ptopic, payload);  // 发布消息
    //         if (rc != 0)                                // 检查是否成功发布消息
    //             printf("MQTT Publish failed!\r\n");
    //         else
    //             printf("MQTT Publish OK\r\n");
    //     }
    //     osDelay(500);                                   // 发布消息间隔5秒
    // }
}

// 入口函数
static void mqttDemoEntry(void)
{
    // 定义线程属性
    osThreadAttr_t attr;
    attr.name = "mqttDemoTask";
    attr.attr_bits = 0U;
    attr.cb_mem = NULL;
    attr.cb_size = 0U;
    attr.stack_mem = NULL;
    attr.stack_size = 10240;
    attr.priority = osPriorityNormal;

    // 创建线程
    if (osThreadNew(mqttDemoTask, NULL, &attr) == NULL)
    {
        printf("[mqttDemoEntry] Falied to create mqttDemoTask!\n");
    }
}

// 运行入口函数
SYS_RUN(mqttDemoEntry);
